﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace XP.Utilities.Utility
{
    public class SqlFilter
    {
        public SqlFilter()
        {
        }

        #region 防止sql注入式攻击(可用于UI层控制）
        /// <SUMMARY>   
        /// 判断字符串中是否有SQL攻击代码 
        /// </SUMMARY>   
        /// <PARAM name="Str">传入用户提交数据</PARAM>   
        /// <RETURNS>true-安全；false-有注入攻击现有；</RETURNS>   
        public bool ProcessSqlStr(string inputString)
        {
            string SqlStr = @"exec|execute|insert |select |delete |update |alter |create |drop |count|\*|substring|master|truncate|declare |xp_cmdshell|restore |backup|net +user|net +localgroup +administrators";
            try
            {
                if ((inputString != null) && (inputString != String.Empty))
                {
                    string str_Regex = @"\b(" + SqlStr + @")\b";

                    Regex Regex = new Regex(str_Regex, RegexOptions.IgnoreCase);
                    //string s = Regex.Match(inputString).Value;    
                    if (true == Regex.IsMatch(inputString))
                        return false;
                }
            }
            catch(Exception ex)
            {
                return false;
            }
            return true;
        }

        /// <SUMMARY>   
        /// 处理用户提交的请求，校验sql注入式攻击,在页面装置时候运行   
        /// System.Configuration.ConfigurationSettings.AppSettings["ErrorPage"].ToString(); 为用户自定义错误页面提示地址,   
        /// 在Web.Config文件时里面添加一个 ErrorPage 即可   
        /// <!-- 防止SQL数据库注入攻击的出错页面自定义地址 -->   
        ///     <ADD key="ErrorPage" value="../Error.html" />   
        /// </SUMMARY>   
        public void ProcessRequest()
        {
            try
            {
                string getkeys = "";
                //string sqlErrorPage = System.Configuration.ConfigurationSettings.AppSettings["ErrorPage"].ToString();
                if (System.Web.HttpContext.Current.Request.QueryString != null)
                {

                    for (int i = 0; i < System.Web.HttpContext.Current.Request.QueryString.Count; i++)
                    {
                        getkeys = System.Web.HttpContext.Current.Request.QueryString.Keys[i];
                        if (!ProcessSqlStr(System.Web.HttpContext.Current.Request.QueryString[getkeys]))
                        {
                            System.Web.HttpContext.Current.Response.Write("错误内容：" + getkeys + "，有SQL攻击嫌疑！");
                            System.Web.HttpContext.Current.Response.End();
                        }
                    }
                }
                if (System.Web.HttpContext.Current.Request.Form != null)
                {
                    for (int i = 0; i < System.Web.HttpContext.Current.Request.Form.Count; i++)
                    {
                        getkeys = System.Web.HttpContext.Current.Request.Form.Keys[i];
                        if (!ProcessSqlStr(System.Web.HttpContext.Current.Request.Form[getkeys]))
                        {
                            System.Web.HttpContext.Current.Response.Write("错误内容：" + getkeys + "，有SQL攻击嫌疑！");
                            System.Web.HttpContext.Current.Response.End();
                        }
                    }
                }
            }
            catch
            {
                // 错误处理: 处理用户提交信息!   
            }
        }
        #endregion

        #region 转换sql代码（也防止sql注入式攻击，可以用于业务逻辑层，但要求UI层输入数据时候进行解码）

        /// <SUMMARY>   
        /// 提取字符固定长度，by fangbo.yu 2008.07.18   
        /// </SUMMARY>   
        /// <PARAM name="inputString"></PARAM>   
        /// <PARAM name="maxLength"></PARAM>   
        /// <RETURNS></RETURNS>   
        public string CheckStringLength(string inputString, Int32 maxLength)
        {
            if ((inputString != null) && (inputString != String.Empty))
            {
                inputString = inputString.Trim();

                if (inputString.Length > maxLength)
                    inputString = inputString.Substring(0, maxLength);
            }
            return inputString;
        }

        /// <SUMMARY>   
        /// 将输入字符串中的sql敏感字，替换成"[敏感字]"，要求输出时，替换回来，by fangbo.yu 2008.07.21   
        /// </SUMMARY>   
        /// <PARAM name="inputstring"></PARAM>   
        /// <RETURNS></RETURNS>   
        public string MyEncodeInputString(string inputString)
        {
            //要替换的敏感字   
            string SqlStr = @"and|or|exec|execute|insert|select|delete|update|alter|create|drop|count|\*|chr|char|asc|mid|substring|master|truncate|declare|xp_cmdshell|restore|backup|net +user|net +localgroup +administrators";
            try
            {
                if ((inputString != null) && (inputString != String.Empty))
                {
                    string str_Regex = @"\b(" + SqlStr + @")\b";

                    Regex Regex = new Regex(str_Regex, RegexOptions.IgnoreCase);
                    //string s = Regex.Match(inputString).Value;    
                    MatchCollection matches = Regex.Matches(inputString);
                    for (int i = 0; i < matches.Count; i++)
                        inputString = inputString.Replace(matches[i].Value, "[" + matches[i].Value + "]");

                }
            }
            catch
            {
                return "";
            }
            return inputString;

        }

        /// <SUMMARY>   
        /// 将已经替换成的"[敏感字]"，转换回来为"敏感字"，by fangbo.yu 2008.07.21   
        /// </SUMMARY>   
        /// <PARAM name="outputstring"></PARAM>   
        /// <RETURNS></RETURNS>   
        public string MyDecodeOutputString(string outputstring)
        {
            //要替换的敏感字   
            string SqlStr = @"and|or|exec|execute|insert|select|delete|update|alter|create|drop|count|\*|chr|char|asc|mid|substring|master|truncate|declare|xp_cmdshell|restore|backup|net +user|net +localgroup +administrators";
            try
            {
                if ((outputstring != null) && (outputstring != String.Empty))
                {
                    string str_Regex = @"\[\b(" + SqlStr + @")\b\]";
                    Regex Regex = new Regex(str_Regex, RegexOptions.IgnoreCase);
                    MatchCollection matches = Regex.Matches(outputstring);
                    for (int i = 0; i < matches.Count; i++)
                        outputstring = outputstring.Replace(matches[i].Value, matches[i].Value.Substring(1, matches[i].Value.Length - 2));

                }
            }
            catch
            {
                return "";
            }
            return outputstring;
        }
        #endregion
    }
}
